{
 "cells": [
  {
   "cell_type": "raw",
   "metadata": {},
   "source": [
    ".. _circuit::\n",
    "\n",
    "|\n",
    "|\n",
    "\n",
    "Download This Notebook: :download:`Circuit.ipynb`"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Circuits\n",
    "## Introduction\n",
    "\n",
    "The [Circuit class](../api/circuit.html) represents a circuit of arbitrary topology, consisting of an arbitrary number of N-ports [Networks](../api/network.html) connected together. Like in an electronic circuit simulator, the circuit must have one (or more) `Port` connected to the circuit. The `Circuit` object allows one retrieving the M-ports `Network` (and thus its network parameters: $S$, $Z$, etc.), where M is the number of ports defined. Moreover, the `Circuit` object also allows calculating the scattering matrix $S$ of the entire circuit, that is the \"internal\" scattering matrices for the various intersections in the circuit. The calculation algorithm is based on ref [1]. \n",
    "\n",
    "The figure below illustrates a network with 2 ports, `Network` elements $N_i$ and intersections:\n",
    "\n",
    "![General Circuit](figures/circuit_general.svg)\n",
    "\n",
    "\n",
    "one must must define the connection list (\"netlist\") of the circuit. This connexion list is defined as a List of List of interconnected Tuples `(network, port_number)`:\n",
    "\n",
    "```\n",
    "connexions = [\n",
    "    [(network1, network1_port_nb), (network2, network2_port_nb), (network2, network2_port_nb), ...],\n",
    "    ...\n",
    "]\n",
    "```\n",
    "\n",
    "For example, the connexion list to construct the above circuit could be: \n",
    "\n",
    "```\n",
    "connexions = [\n",
    "    [(port1, 0), (network1, 0), (network4, 0)],\n",
    "    [(network1, 1), (network2, 0), (network5, 0)],\n",
    "    [(network1, 2), (network3, 0)],\n",
    "    [(network2, 1), (network3, 1)],\n",
    "    [(network2, 2), (port2, 0)],\n",
    "    [(network5, 1), (ground1, 0)]\n",
    "]\n",
    "```\n",
    "\n",
    "where we have assumed that `port1`, `port2`, `ground1` and all the `network1` to `network5` are scikit-rf [Networks](../api/network.html) objects with same `Frequency`. Networks can have different (real) characteristic impedances: mismatch are taken into account. Convenience methods are provided to create ports and grounded connexions: the [Circuit.Port()](../api/generated/skrf.circuit.Circuit.Port.html#skrf.circuit.Circuit.Port) and [Circuit.Ground()](../api/generated/skrf.circuit.Circuit.Ground.html#skrf.circuit.Circuit.Ground) methods. Note that the port 1 of the network4 is left open, so is not described in the connexion list.\n",
    "\n",
    "Once the connexion list is defined, the `Circuit` with:\n",
    "\n",
    "```\n",
    "resulting_circuit = rf.Circuit(connexions)\n",
    "```\n",
    "`resulting_circuit` is a [Circuit](../api/circuit.html) object. \n",
    "\n",
    "The resulting 2-ports `Network` is obtained with the [Circuit.network](../api/generated/skrf.circuit.Circuit.network.html#skrf.circuit.Circuit.network) parameter:\n",
    "\n",
    "```\n",
    "resulting_network = resulting_circuit.network\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Note that it is also possible to create manually a circuit of multiple `Network` objects using the [connecting methods](../api/network.html#connecting-networks) of `scikit-rf`. Although the `Circuit` approach to build a multiple `Network` may appear to be more verbose than the 'classic' way for building a circuit, as the circuit complexity increases, in particular when components are connected in parallel, the `Circuit` approach is interesting as it increases the readability of the code. Moreover, `Circuit` circuit topology can be plotted using its `plot_graph` method, which is usefull to rapidly control if the circuit is built as expected. \n",
    "\n",
    "\n",
    "[1] Hallbjörner, P., 2003. Method for calculating the scattering matrix of arbitrary microwave networks giving both internal and external scattering. Microw. Opt. Technol. Lett. 38, 99–102. https://doi.org/10/d27t7m"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Examples\n",
    "### Loaded transmission line\n",
    "Assume that a $50\\Omega$ lossless transmission line is loaded with a $Z_L=75\\Omega$ impedance. \n",
    "\n",
    "![Loaded Transmission Line Circuit](figures/circuit_loaded_transmission_line1.svg)\n",
    "\n",
    "If the transmission line electric length is $\\theta=0$, then one would thus expect the reflection coefficient to be:\n",
    "\n",
    "$$\n",
    "\\rho = s = \\frac{Z_L - Z_0}{Z_L + Z_0} = 0.2\n",
    "$$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import skrf as rf\n",
    "rf.stylely()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "Z_0 = 50\n",
    "Z_L = 75\n",
    "theta = 0\n",
    "\n",
    "# the necessary Frequency description\n",
    "freq = rf.Frequency(start=1, stop=2, unit='GHz', npoints=3)\n",
    "\n",
    "# The combination of a transmission line + a load can be created\n",
    "# using the convenience delay_load method\n",
    "# important: all the Network must have the parameter \"name\" defined \n",
    "tline_media = rf.DefinedGammaZ0(freq, z0=Z_0)\n",
    "delay_load = tline_media.delay_load(rf.zl_2_Gamma0(Z_0, Z_L), theta, unit='deg', name='delay_load')\n",
    "\n",
    "# the input port of the circuit is defined with the Circuit.Port method\n",
    "# In order for Circuit() to recognize the Network as a \"port\", its name must contains the word 'port':\n",
    "port1 = rf.Circuit.Port(freq, 'port1', z0=Z_0)\n",
    "\n",
    "# connexion list\n",
    "cnx = [\n",
    "    [(port1, 0), (delay_load, 0)]\n",
    "]\n",
    "# building the circuit\n",
    "cir = rf.Circuit(cnx)\n",
    "\n",
    "# getting the resulting Network from the 'network' parameter:\n",
    "ntw = cir.network\n",
    "print(ntw)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# as expected the reflection coefficient is:\n",
    "print(ntw.s[0])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "It is also possible to build the above circuit using a series impedance Network, then shorted:\n",
    "\n",
    "![Loaded Transmission Line Circuit: 2nd version](figures/circuit_loaded_transmission_line2.svg)\n",
    "\n",
    "To do so, one would need to use the `Ground()` method to generate the required `Network` object. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "port1 = rf.Circuit.Port(freq, 'port1', z0=Z_0)\n",
    "# piece of transmission line and series impedance\n",
    "trans_line = tline_media.line(theta, unit='deg', name='trans_line')\n",
    "load = tline_media.resistor(Z_L, name='delay_load')\n",
    "# ground network (short)\n",
    "ground = rf.Circuit.Ground(freq, name='ground')\n",
    "\n",
    "# connexion list\n",
    "cnx = [\n",
    "    [(port1, 0), (trans_line, 0)],\n",
    "    [(trans_line, 1), (load, 0)],\n",
    "    [(load, 1), (ground, 0)]\n",
    "]\n",
    "# building the circuit\n",
    "cir = rf.Circuit(cnx)\n",
    "# the result if the same : \n",
    "print(cir.network.s[0])\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### LC Filter\n",
    "Here we model a low-pass LC filter, with example values taken from [rf-tools.com](https://rf-tools.com/lc-filter/) :\n",
    "\n",
    "![low pass filter](figures/circuit_filter1.svg)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "freq = rf.Frequency(start=0.1, stop=10, unit='GHz', npoints=1001)\n",
    "tl_media = rf.DefinedGammaZ0(freq, z0=50, gamma=1j*freq.w/rf.c)\n",
    "C1 = tl_media.capacitor(3.222e-12, name='C1')\n",
    "C2 = tl_media.capacitor(82.25e-15, name='C2')\n",
    "C3 = tl_media.capacitor(3.222e-12, name='C3')\n",
    "L2 = tl_media.inductor(8.893e-9, name='L2')\n",
    "RL = tl_media.resistor(50, name='RL')\n",
    "gnd = rf.Circuit.Ground(freq, name='gnd')\n",
    "port1 = rf.Circuit.Port(freq, name='port1', z0=50) \n",
    "port2 = rf.Circuit.Port(freq, name='port2', z0=50)\n",
    "\n",
    "cnx = [\n",
    "    [(port1, 0), (C1, 0), (L2, 0), (C2, 0)],\n",
    "    [(L2, 1), (C2, 1), (C3, 0), (port2, 0)],\n",
    "    [(gnd, 0), (C1, 1), (C3, 1)],\n",
    "]\n",
    "cir = rf.Circuit(cnx)\n",
    "ntw = cir.network"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "ntw.plot_s_db(m=0, n=0, lw=2, logx=True)\n",
    "ntw.plot_s_db(m=1, n=0, lw=2, logx=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "When building a `Circuit` made of few networks, it can be usefull to represent the connexion graphically, in order to check for possible errors. This is possible using the [Circuit.plot_graph()](../api/circuit.html#representing-a-circuit) method. Ports are indicated by triangles, Network with squares and interconnections with circles. It is possible to display the network names as well as their associated ports (and characteristic impedances): "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "cir.plot_graph(network_labels=True, network_fontsize=15, \n",
    "               port_labels=True, port_fontsize=15,\n",
    "              edge_labels=True, edge_fontsize=10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
